#pragma once
#include <string>
#include <vector>
#include <map>
#include <curl/curl.h>
#include "BBS2chProxyConnection.h"
#include "BBS2chProxyHttpHeaders.h"
#include "BBS2chProxyFormData.h"
#include "BBS2chProxyURL.h"

class IBBS2chProxyPoster {
protected:
	std::string _url;
	BBS2chProxyHttpHeaders &_requestHeaders;
	BBS2chProxyFormData &_requestBody;
	std::string _host;
	std::string _board;
	std::string _thread;
	std::string _nic;
	std::string _forceProxy;
	long _verbose;
	void prepareHeadersAndBody(const BBS2chProxyURL &url);
	curl_slist* prepareCurlHandle(BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body, curl_slist* headersForCurl);
	void runLuaScript(BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body);
public:
	BBS2chProxyConnection *connectionDelegate;
	std::string _userAgentForRequest;
	std::string _monaKeyForRequest;
	bool _manageCookies;
	IBBS2chProxyPoster(BBS2chProxyURL &url, BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body, BBS2chProxyConnection *delegate);
	virtual ~IBBS2chProxyPoster() {};
	virtual long post() = 0;
	std::string identifier();
};

class BBS2chProxy5chPoster : public IBBS2chProxyPoster {
protected:
	void makeSignature(BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body);
public:
	struct ConfirmationManager {
		pthread_mutex_t _mutex;
		std::map<std::string, std::pair<time_t, PBBS2chProxyFormData> > _cachedForms;
		time_t _lastCached;
		ConfirmationManager() : _lastCached() {
			pthread_mutex_init(&_mutex, NULL);
		}
		~ConfirmationManager() {
			pthread_mutex_destroy(&_mutex);
		}
		void add(IBBS2chProxyPoster &poster, PBBS2chProxyFormData body);
		bool modifyRequestBodyIfNeeded(IBBS2chProxyPoster &poster, BBS2chProxyFormData &body);
	};
	bool _isFirstRun;
	int _status;
	bool _isResponseChunked;
	std::string _responseHeaders;
	bool _hasSetCookie;
	std::vector<char> _responseBody;
	bool _useTransparentContentEncoding;
	int _confirmationHandlerMode;
	bool _hasAcceptEncoding;
	static ConfirmationManager confirmationManager;
	BBS2chProxy5chPoster(BBS2chProxyURL &url, BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body, BBS2chProxyConnection *delegate);
	virtual ~BBS2chProxy5chPoster() {};
	virtual long post();
};

class BBS2chProxyTalkPoster : public IBBS2chProxyPoster {
	void makeSignature(BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body);
public:
	BBS2chProxyTalkPoster(BBS2chProxyURL &url, BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body, BBS2chProxyConnection *delegate);
	virtual ~BBS2chProxyTalkPoster() {};
	virtual long post();
};

class BBS2chProxyTalkTo5chPoster : public BBS2chProxy5chPoster {
public:
	BBS2chProxyTalkTo5chPoster(BBS2chProxyURL &url, BBS2chProxyHttpHeaders &headers, BBS2chProxyFormData &body, BBS2chProxyConnection *delegate);
	virtual ~BBS2chProxyTalkTo5chPoster() {};
	virtual long post();
};
